package gui;

import java.io.Writer;
import java.util.Set;

import exception.IllegalPositionException;
import exception.IllegalPositionOnBoardException;
import exception.NegativeAmountException;

import roborally.board.*;
import roborally.factory.PhysicalAmountFactory;
import roborally.factory.PositionFactory;
import roborally.itemsonboard.*;
import roborally.supporting.DefaultConstants;
import roborally.supporting.Direction;
import roborally.supporting.Orientation;
import roborally.supporting.PhysicalAmount;
import roborally.supporting.Position;
import roborally.supporting.Unit;

public class Facade implements
		IFacade<Board, Robot, Wall, Battery, RepairKit, SurpriseBox> {

	/**
	 * Creates a new board if the arguments are valid, otherwise returns null.
	 * 
	 * @param width The x coordinate for the board.
	 * @param height The y coordinate for the board.
	 * @return
	 * 		| if Board.isValidXLimit(xLimit) && Board.isValidYLimit(yLimit)
	 * 		|	then result == new Board(width, height)
	 * 		| else
	 * 		|	then result == null
	 */
	@Override
	public Board createBoard(long width, long height) {
		try {
			return new Board(width, height);
		} catch(IllegalArgumentException exc) {
			return null;
		}
	}

	/**
	 * Merges board1 with board2. All the items on board2 will be put on board1 if possible.
	 * If possible, they will be set on the corresponding position.
	 * Otherwise they will be terminated together with board2.
	 * 
	 * @param board1 The board that will contain the items of board2 if possible.
	 * @param board2 The board that will terminated with the items that can not be placed on board1.
	 * @effect
	 * 		| if !(board1 == null || board1.isTerminated() || board2 == null || board2.isTerminated())
	 * 		|	then board1.merge(board2)
	 */
	@Override
	public void merge(Board board1, Board board2) {
		if(board1 == null || board1.isTerminated() || board2 == null || board2.isTerminated())
			System.err.print("The arguments are not valid.");
		else {
			board1.merge(board2);
		}	
	}

	/**
	 * Creates a new battery with the given options.
	 * 
	 * @param initialEnergy The initialEnergy of this battery.
	 * @param weight The weight of this battery.
	 * @return
	 * 		| if !Battery.isValidWeight(weight)
	 * 		|	then result == null
	 * 		| else
	 * 		|	let temp = new Battery(weight)
	 * 		|	if !PhysicalAmount.isValidAmount(initialEnergy) || !temp.canHaveAsEnergyLevel(PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 * 		|		then result == null
	 * 		|	else
	 * 		|		then result == new Battery(weight, PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 */
	@Override
	public Battery createBattery(double initialEnergy, int weight) {
		if(!PhysicalAmount.isValidAmount(weight))
			return null;
		if(!PhysicalAmount.isValidAmount(initialEnergy))
			return null;
		PhysicalAmount weightP = PhysicalAmountFactory.get().create(weight, Unit.GRAM);
		PhysicalAmount initialEnergyP = PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND);
		if(!Battery.isValidWeight(weightP))
			return null;
		try {
			Battery battery = new Battery(weightP);
			if(battery.canHaveAsEnergyLevel(initialEnergyP)) {
				battery.setEnergyLevel(initialEnergyP);
				return battery;
			}
			return null;
		} catch(IllegalArgumentException exc) {
			System.err.println(exc);
			return null;
		}
	}

	/**
	 * Puts a battery to the given board if possible.
	 * 
	 * @param board The board where the battery will be placed onto.
	 * @param x The x coordinate where the battery will be placed.
	 * @param y The y coordinate where the battery will be placed.
	 * @param battery The battery that will be placed
	 * @post
	 * 		| let tempBattery = battery.setBoard(null)
	 * 		| tempBattery = tempBattery.setPosition(PositionFactory.getInstance().newPosition(x,y))
	 * 		| if board != null && battery != null && !board.isTerminated() && !battery.isTerminated()
	 * 		| 		&& Position.isValidX(x) && Position.isValid(y) && board.canHaveAsItem(tempBattery)
	 * 		| 	then ( board.getItemsAt(PositionFactory.getInstance().newPosition(x,y)).contains((new battery))
	 * 		|			 && (new battery).getPosition.equals(PositionFactory.getInstance().newPosition(x,y))
	 * 		|			 && (new battery).getBoard() == board )
	 */
	@Override
	public void putBattery(Board board, long x, long y, Battery battery) {
		if(board == null || battery == null || board.isTerminated() || battery.isTerminated()) 
			System.err.print("The board is null or/and the battery is null, or/and the board or/and the battery is terminated");
		else{
			Position tempPosition = battery.getPosition();
			Board tempBoard=battery.getBoard();
			if(tempBoard != null)
				tempBoard.removeAsItem(battery);
			try {
				battery.setPosition(PositionFactory.get().create(x,y)); // no exceptions should be thrown here. unless at the creation of the Position.
				board.addAsItem(battery);
			} catch(IllegalArgumentException exc) { // restore battery
				battery.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(battery);
				System.err.print(exc);
			} catch(IllegalPositionException exc) { // restore battery
				battery.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(battery);
				System.err.print(exc);
			} 
		}		
	}

	/**
	 * When a battery is placed onto a board, return the x coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param battery The battery of which the x coordinate must be retrieved.
	 * @pre
	 * 		| battery != null
	 * @return
	 * 		| result == battery.getPosition().getX()
	 * @throws IllegalStateException
	 * 		| battery.getBoard() == null
	 */
	@Override
	public long getBatteryX(Battery battery) throws IllegalStateException {
		assert battery != null;
		if(battery.getBoard() == null)
			throw new IllegalStateException();
		else
			return battery.getPosition().getX();
	}

	/**
	 * When a battery is placed onto a board, return the y coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param battery The battery of which the y coordinate must be retrieved.
	 * @pre
	 * 		| battery != null
	 * @return
	 * 		| result == battery.getPosition().getY()
	 * @throws IllegalStateException
	 * 		| battery.getBoard() == null
	 */
	@Override
	public long getBatteryY(Battery battery) throws IllegalStateException {
		assert battery != null;
		if(battery.getBoard() == null)
			throw new IllegalStateException();
		else
			return battery.getPosition().getY();
	}

	/**
	 * Creates a new RepairKit with the given options.
	 * 
	 * @param initialEnergy The initialEnergy of this RepairKit.
	 * @param weight The weight of this RepairKit.
	 * @return
	 * 		| if !RepairKit.isValidWeight(weight)
	 * 		|	then result == null
	 * 		| else
	 * 		|	let temp = new RepairKit(weight)
	 * 		|	if !PhysicalAmount.isValidAmount(initialEnergy) || !temp.canHaveAsEnergyLevel(PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 * 		|		then result == null
	 * 		|	else
	 * 		|		then result == new RepairKit(weight, PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 */
	@Override
	public RepairKit createRepairKit(double repairAmount, int weight) {
		if(!PhysicalAmount.isValidAmount(weight))
			return null;
		if(!PhysicalAmount.isValidAmount(repairAmount))
			return null;
		PhysicalAmount weightP = PhysicalAmountFactory.get().create(weight, Unit.GRAM);
		PhysicalAmount initialEnergyP = PhysicalAmountFactory.get().create(repairAmount, Unit.WATTSECOND);
		if(!RepairKit.isValidWeight(weightP))
			return null;
		try {
			RepairKit repairKit = new RepairKit(weightP);
			if(repairKit.canHaveAsEnergyLevel(initialEnergyP)) {
				repairKit.setEnergyLevel(initialEnergyP);
				return repairKit;
			}
			return null;
		} catch(IllegalArgumentException exc) {
			System.err.println(exc);
			return null;
		}
	}

	@Override
	public void putRepairKit(Board board, long x, long y, RepairKit repairKit) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public long getRepairKitX(RepairKit repairKit) throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public long getRepairKitY(RepairKit repairKit) throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public SurpriseBox createSurpriseBox(int weight) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void putSurpriseBox(Board board, long x, long y,
			SurpriseBox surpriseBox) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public long getSurpriseBoxX(SurpriseBox surpriseBox)
			throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public long getSurpriseBoxY(SurpriseBox surpriseBox)
			throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	/**
	 * Creates a new robot on the origin with given orientation and energy level.
	 * 
	 * @param orientation The orientation of the robot.
	 * @param initialEnergy The initial energy of the robot.
	 * @return
	 * 		| let robot = new Robot()
	 * 		|	if !PhysicalAmount.isValidAmount(amount) && !robot.canHaveAsEnergyLevel(PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 * 		|		result == null
	 * 		|	else
	 * 		|		result == new Robot(Position.Origin, Orientation.values()[Math.abs(orientation % 4)], PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND))
	 */
	@Override
	public Robot createRobot(int orientation, double initialEnergy) {
		Robot robot = new Robot();
		try {
			PhysicalAmount temp = PhysicalAmountFactory.get().create(initialEnergy, Unit.WATTSECOND);
			if(!robot.canHaveAsEnergyLevel(temp))
				return null;
			else 
				return new Robot(Position.ORIGIN, Orientation.values()[Math.abs(orientation % 4)], temp);
		} catch (IllegalArgumentException exc) {
			return null;
		} catch (NegativeAmountException exc2) {
			return null;
		}
	}

	/**
	 * Puts a robot to the given board if possible.
	 * 
	 * @param board The board where the robot will be placed onto.
	 * @param x The x coordinate where the robot will be placed.
	 * @param y The y coordinate where the robot will be placed.
	 * @param robot The robot that will be placed
	 * @post
	 * 		| let tempRobot = robot.setBoard(null)
	 * 		| tempRobot = tempRobot.setPosition(PositionFactory.getInstance().newPosition(x,y))
	 * 		| if board != null && wall != null && Position.isValidX(x)
	 * 		|		&& Position.isValid(y) && board.canHaveAsItem(tempRobot)
	 * 		| 	then ( board.getItemsAt(PositionFactory.getInstance().newPosition(x,y)).contains((new robot))
	 * 		|			 && (new robot).getPosition.equals(PositionFactory.getInstance().newPosition(x,y))
	 * 		|			 && (new robot).getBoard() == board )
	 */	
	@Override
	public void putRobot(Board board, long x, long y, Robot robot) { 
		if(board == null || robot == null) 
			System.err.print("The board is null or/and the wall is null");
		else{
			Position tempPosition = robot.getPosition();
			Board tempBoard=robot.getBoard();
			if(tempBoard != null)
				tempBoard.removeAsItem(robot);
			try {
				robot.setPosition(PositionFactory.get().create(x,y)); // no exceptions should be thrown here. unless at the creation of the Position.
				board.addAsItem(robot);
			} catch(IllegalArgumentException exc) {
				robot.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(robot);
				System.err.print(exc);
			} catch(IllegalPositionException exc) {
				robot.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(robot);
				System.err.print(exc);
			} 
		}
	}

	/**
	 * When a robot is placed onto a board, return the x coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param robot The robot of which the x coordinate must be retrieved.
	 * @pre
	 * 		| robot != null
	 * @return
	 * 		| result == robot.getPosition().getX()
	 * @throws IllegalStateException
	 * 		| robot.getBoard() == null
	 */
	@Override
	public long getRobotX(Robot robot) throws IllegalStateException {
		assert robot != null;
		if(robot.getBoard() == null)
			throw new IllegalStateException();
		else
			return robot.getPosition().getX();
	}

	/**
	 * When a robot is placed onto a board, return the y coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param robot The robot of which the y coordinate must be retrieved.
	 * @pre
	 * 		| robot != null
	 * @return
	 * 		| result == robot.getPosition().getY()
	 * @throws IllegalStateException
	 * 		| robot.getBoard() == null
	 */
	@Override
	public long getRobotY(Robot robot) throws IllegalStateException {
		assert robot != null;
		if(robot.getBoard() == null)
			throw new IllegalStateException();
		else
			return robot.getPosition().getY();
	}

	/**
	 * Returns the orientation of this robot.
	 * 
	 * @param robot The robot of with orientation must be returned.
	 * @pre
	 * 		| robot != null
	 * @return
	 * 		| result == robot.getOrientation().getOrientation()
	 */
	@Override
	public int getOrientation(Robot robot) {
		assert robot != null;
		return robot.getOrientation().getOrientation();
	}

	/**
	 * Returns the energy of this robot in WattSecond.
	 * 
	 * @param robot The robot of which energy must be returned.
	 * @pre
	 * 		| robot != null
	 * @return
	 * 		| result == robot.getEnergyLevel()
	 */
	@Override
	public double getEnergy(Robot robot) {
		assert robot != null;
		return robot.getEnergyLevel().getAmount();
	}

	/**
	 * Moves the robot if possible.
	 * 
	 * @param robot The robot that will be moved.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| let cost = DefaultConstants.ROBOT_ENERGY_MOVEMENT.add(DefaultConstants.ROBOT_ENERGY_MOVEMENT_PER_WEIGHT * robot.getWeightCarried())
	 * 		| if PhysicalAmount.isValidAmount(robot.getEnergyLevel().getAmount() - cost.getAmount() 
	 * 		|		&& robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(cost)  && !robot.isTerminated()
	 * 		|	then if robot.getOrientation() == Orientation.UP
	 * 		|		then if Position.isValidX(robot.getPosition().getX()) && Position.isValidY(robot.getPosition().getY() - 1)
	 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
	 * 		|				then robot.move()
	 * 		|   else if robot.getOrientation() == Orientation.RIGHT
	 * 		|		then if Position.isValidX(robot.getPosition().getX() + 1) && Position.isValidY(robot.getPosition().getY())
	 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
	 * 		|				then robot.move()
	 * 		|	else if robot.getOrientation() == Orientation.DOWN
	 * 		|		then if Position.isValidX(robot.getPosition().getX()) && Position.isValidY(robot.getPosition().getY() + 1)
	 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
	 * 		|				then robot.move()
	 * 		|	else if robot.getOrientation() == Orientation.LEFT
	 * 		|		then if Position.isValidX(robot.getPosition().getX() - 1) && Position.isValidY(robot.getPosition().getY())
	 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
	 * 		|				then robot.move()   
	 */
	@Override
	public void move(Robot robot) {
		assert robot != null;
		try {
			if(robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_MOVEMENT).subtract( 
					PhysicalAmountFactory.get().create(robot.getWeightCarried().getAmount() * DefaultConstants.ROBOT_ENERGY_MOVEMENT_PER_WEIGHT, Unit.WATTSECOND)))) 
				robot.move();
		
		}catch(NegativeAmountException exc){
			// not enough energy
		}catch(IllegalStateException exc) {
			System.err.print(exc);
		} catch(IllegalPositionException exc) {
			System.err.print(exc);
		} catch(IllegalPositionOnBoardException exc) {
			System.err.print(exc);
		}
	}

	/**
	 * Turns the robot one step clockwise if he has enough energy.
	 * 
	 * @param robot The robot to be turned.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| if PhysicalAmount.isValidAmount(robot.getEnergyLevel().getAmount() - DefaultConstants.ROBOT_ENERGY_TURN.getAmount())
	 * 		|		&& robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_TURN))
	 * 		| 	then robot.turn(Direction.CLOCKWISE)
	 * @note If the robot is terminated, nothing will happen.
	 */
	@Override
	public void turn(Robot robot) {
		assert robot != null;
		if(PhysicalAmount.isValidAmount(robot.getEnergyLevel().getAmount() - DefaultConstants.ROBOT_ENERGY_TURN.getAmount())
				&& robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_TURN)))
			robot.turn(Direction.CLOCKWISE);
	}

	/**
	 * The robot will pick up a battery if possible
	 * 
	 * @param robot The robot that will pick up a battery.
	 * @param battery The battery that will be picked up.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| if robot.canPickUp(battery)
	 * 		|	then robot.pickUp(battery)
	 */
	@Override
	public void pickUpBattery(Robot robot, Battery battery) {
		assert robot != null;
		if(robot.canPickUp(battery)) {
			robot.pickUp(battery);
			assert battery.getBoard() == null;
			assert !robot.getBoard().getItemsAt(robot.getPosition()).contains(battery);
		}
		else
			System.err.print("The robot is terminated and/or the battery can not be picked up by" +
					" the robot");
	}

	/**
	 * The robot will use the battery if possible.
	 * 
	 * @param robot The robot that will use the battery.
	 * @param battery The battery that will be used by the robot.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| if robot.canUse(battery)
	 * 		|	then robot.use(battery)
	 */
	@Override
	public void useBattery(Robot robot, Battery battery) {
		assert robot != null;
		if(robot.canUse(battery))
			robot.use(battery);
		else
			System.err.print("The battery is null or the robot is terminated or the robot doesn't possess the battery.");
	}

	/**
	 * The given robot will drop the battery if he is carrying the battery.
	 * 
	 * @param robot The robot that will drop the battery.
	 * @param battery The battery that will be dropped from the robot.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| if robot.canDrop(battery)
	 * 		|	then robot.drop(battery)
	 */
	@Override
	public void dropBattery(Robot robot, Battery battery) {
		assert robot != null;
		if(robot.canDrop(battery))
			robot.drop(battery);
	}

	@Override
	public void pickUpRepairKit(Robot robot, RepairKit repairKit) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void useRepairKit(Robot robot, RepairKit repairKit) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dropRepairKit(Robot robot, RepairKit repairKit) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pickUpSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void useSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dropSurpriseBox(Robot robot, SurpriseBox surpriseBox) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void transferItems(Robot from, Robot to) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * We take into account that turning consumes energy and that there are obstacles.
	 */
	@Override
	public int isMinimalCostToReach17Plus() {
		return 1;
	}

	/**
	 * Returns the minimal energy for the given robot to reach the given position.
	 * 
	 * @param robot The robot that should move.
	 * @param x The x coordinate of the position.
	 * @param y The y coordinate of the position.
	 * @pre
	 * 		| robot != null
	 * @return	
	 * 		| if Position.isValidX(x) && Position.isValidY(y)
	 * 		|	then let temp Double temp = robot.getEnergyRequiredToReach(destination).getAmount();
	 * 		|		 if temp == Double.POSITIVE_INFINITY
	 * 		|			then result == -1
	 * 		|		 else
	 * 		|			then result == robot.getEnergyRequiredToReach(destination)
	 * 		| else
	 * 		|	result == -1
	 */
	@Override
	public double getMinimalCostToReach(Robot robot, long x, long y) {
		assert robot != null;
		try {
			Position destination = PositionFactory.get().create(x,y);
			Double temp = robot.getEnergyRequiredToReach(destination).getAmount();
			if(temp == Double.POSITIVE_INFINITY)
				return -1;
			return temp;
		} catch(IllegalPositionException exc) {
			return -1;
		}
	}

	/**
	 * We take into account that turning consumes energy and that there are obstacles.
	 */
	@Override
	public int isMoveNextTo18Plus() {
		return 1;
	}

	/**
	 * Moves the robot and other as close as possible to each other without inefficient movements and
	 * turnings.
	 * 
	 * @param robot The robot that will move towards the other.
	 * @param other The other that will move towards the robot.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| if other != null && !robot.isTerminated() && !other.isTerminated() && robot.getBoard() != null
	 * 		|		&& robot.getBoard() == other.getBoard() && robot != other
	 * 		|	then robot.moveNextTo(other)
	 */
	@Override
	public void moveNextTo(Robot robot, Robot other) {
		assert robot != null;
		try {
			robot.moveNextTo(other);
		} catch(IllegalArgumentException exc) {
			System.err.print(exc);
		} catch(IllegalStateException exc) {
			System.err.print(exc);
		}
	}

	/**
	 * The robot will shoot in a given direction if he has enough energy and is
	 * placed on a board.
	 * 
	 * @param robot The robot that will shoot.
	 * @pre
	 * 		| robot != null
	 * @effect
	 * 		| robot.shoot()
	 */
	@Override
	public void shoot(Robot robot) throws UnsupportedOperationException {
		assert robot != null;
		robot.shoot();
	}

	/**
	 * Creates a new wall at the origin position and with no board.
	 * 
	 * @return
	 * 		| result == new Wall()
	 */
	@Override
	public Wall createWall() throws UnsupportedOperationException {
		return new Wall();
	}

	/**
	 * Puts a wall to the given board if possible.
	 * 
	 * @param board The board where the wall will be placed onto.
	 * @param x The x coordinate where the wall will be placed.
	 * @param y The y coordinate where the wall will be placed.
	 * @param wall The wall that will be placed
	 * @post
	 * 		| let tempWall = wall.setBoard(null)
	 * 		| tempWall = tempWall.setPosition(PositionFactory.getInstance().newPosition(x,y))
	 * 		| if board != null && wall != null && Position.isValidX(x)
	 * 		|		&& Position.isValid(y) && board.canHaveAsItem(tempWall)
	 * 		| 	then ( board.getItemsAt(PositionFactory.getInstance().newPosition(x,y)).contains((new wall))
	 * 		|			 && (new wall).getPosition.equals(PositionFactory.getInstance().newPosition(x,y))
	 * 		|			 && (new wall).getBoard() == board )
	 */
	@Override
	public void putWall(Board board, long x, long y, Wall wall) 
			throws UnsupportedOperationException {
		if(board == null || wall == null) 
			System.err.print("The board is null or/and the wall is null");
		else{
			Position tempPosition = wall.getPosition();
			Board tempBoard=wall.getBoard();
			if(tempBoard != null)
				tempBoard.removeAsItem(wall);
			try {
				wall.setPosition(PositionFactory.get().create(x,y)); // no exceptions should be thrown here. unless at the creation of the Position.
				board.addAsItem(wall);
			} catch(IllegalArgumentException exc) {
				wall.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(wall);
				System.err.print(exc);
			} catch(IllegalPositionException exc) {
				wall.setPosition(tempPosition);
				if(tempBoard!= null)
					tempBoard.addAsItem(wall);
				System.err.print(exc);
			} 
		}
	}

	/**
	 * When a wall is placed onto a board, return the x coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param wall The wall of which the x coordinate must be retrieved.
	 * @pre
	 * 		| wall != null
	 * @return
	 * 		| result == wall.getPosition().getX()
	 * @throws IllegalStateException
	 * 		| wall.getBoard() == null
	 */
	@Override
	public long getWallX(Wall wall) throws IllegalStateException,
			UnsupportedOperationException {
		assert wall != null;
		if(wall.getBoard() == null)
			throw new IllegalStateException();
		else
			return wall.getPosition().getX();
	}

	/**
	 * When a wall is placed onto a board, return the y coordinate of his position. Otherwise 
	 * a IllegalStateException will be thrown.
	 * 
	 * @param wall The wall of which the y coordinate must be retrieved.
	 * @pre
	 * 		| wall != null
	 * @return
	 * 		| result == wall.getPosition().getY()
	 * @throws IllegalStateException
	 * 		| wall.getBoard() == null
	 */
	@Override
	public long getWallY(Wall wall) throws IllegalStateException,
			UnsupportedOperationException {
		assert wall != null;
		if(wall.getBoard() == null)
			throw new IllegalStateException();
		else
			return wall.getPosition().getY();
	}

	/**
	 * Returns all the robots on the given board.
	 * 
	 * @param board The board of which the robots must be returned.
	 * @pre
	 * 		| board != null
	 * @return
	 * 		| result == board.getAllItemsType(Robot.class)
	 */
	@Override
	public Set<Robot> getRobots(Board board) {
		assert board != null;
		return board.getAllItemsType(Robot.class);
	}

	/**
	 * Returns all the walls on the given board.
	 * 
	 * @param board The board of which the walls must be returned.
	 * @pre
	 * 		| board != null
	 * @return
	 * 		| result == board.getAllItemsType(Wall.class)
	 */
	@Override
	public Set<Wall> getWalls(Board board) throws UnsupportedOperationException {
		assert board != null;
		return board.getAllItemsType(Wall.class);
	}

	@Override
	public Set<RepairKit> getRepairKits(Board board) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Set<SurpriseBox> getSurpriseBoxes(Board board) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * Returns all the batteries on the given board.
	 * 
	 * @param board The board of which the batteries must be returned.
	 * @pre
	 * 		| board != null
	 * @return
	 * 		| result == board.getAllItemsType(Battery.class)
	 */
	@Override
	public Set<Battery> getBatteries(Board board) {
		assert board != null;
		return board.getAllItemsType(Battery.class);
	}

	@Override
	public int loadProgramFromFile(Robot robot, String path) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public int saveProgramToFile(Robot robot, String path) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void prettyPrintProgram(Robot robot, Writer writer) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stepn(Robot robot, int n) {
		// TODO Auto-generated method stub
		
	}

}
